#ifndef T_BEND_PROCESS_H
#define T_BEND_PROCESS_H

#include "t_core.h"

class T_HttpAccessBackend_Process: public T_HttpAccessReplyBackend
{
    Q_OBJECT
protected:
    QString f_exeName;
    QProcess f_process;
    QNetworkRequest f_request;
    T_NetworkReply_Parser f_http_attr;
public:
    explicit T_HttpAccessBackend_Process(T_NetworkAccessManager * nam, QString exeName)
        : T_HttpAccessReplyBackend(nam)
        , f_exeName(exeName)
    {
        qDebug() << "[T_HttpAccessBackend_Process::T_HttpAccessBackend_Process()]" << f_exeName;
    }
    virtual ~T_HttpAccessBackend_Process()
    {
        qDebug() << "[T_HttpAccessBackend_Process::~T_HttpAccessBackend_Process()]";
    }
    //
    virtual void start(T_NetworkAccessManager * nam,
                       QNetworkAccessManager::Operation op,
                       const QNetworkRequest & request,
                       QIODevice * outgoingData)
    {
        Q_UNUSED(nam); Q_UNUSED(op); Q_UNUSED(request); Q_UNUSED(outgoingData);
        qDebug() << "[T_HttpAccessBackend_Process::start(1)]";
        f_process.setReadChannel(QProcess::StandardOutput);
        connect(&f_process, SIGNAL(started()), this, SLOT(self_process_started()));
        connect(&f_process, SIGNAL(finished(int,QProcess::ExitStatus)),
                this, SLOT(self_process_finished(int,QProcess::ExitStatus)));
        connect(&f_process, SIGNAL(readyReadStandardOutput()), this, SLOT(self_process_readyReadStandardOutput()));
        connect(&f_process, SIGNAL(readyReadStandardError()), this, SLOT(self_process_readyReadStandardError()));
        f_process.start(f_exeName, QIODevice::ReadWrite);
        qDebug() << "[T_HttpAccessBackend_Process::start(2)]";
    }
    // raw headers:
    virtual bool hasRawHeader(const QByteArray &headerName) const
    {
        return f_http_attr.hasRawHeader(headerName);
    }
    virtual QList<QByteArray> rawHeaderList() const
    {
        return f_http_attr.rawHeaderList();
    }
    virtual QByteArray rawHeader(const QByteArray &headerName) const
    {
        return f_http_attr.rawHeader(headerName);
    }
    // attributes
    virtual QVariant attribute(QNetworkRequest::Attribute code) const
    {
        return f_http_attr.attribute(code);
    }
    // reading
    virtual qint64 bytesAvailable()
    {
        return f_process.bytesAvailable();
    }
    virtual QByteArray read(qint64 a_max)
    {
        return f_process.read(a_max);
    }
private slots:
    void self_process_started()
    {
        qDebug() << "[T_HttpAccessBackend_Process::self_process_started(1)]" << backend();
        QNetworkRequest v_request = backend()->request();
        qDebug() << "[T_HttpAccessBackend_Process::self_process_started(2)]";
        f_process.write("GET ");
        f_process.write(v_request.url().toEncoded());
        f_process.write(" HTTP/1.1");
        f_process.write("\r\n");
        QList<QByteArray> v_header_list = v_request.rawHeaderList();
        foreach(QByteArray v_header, v_header_list)
        {
            f_process.write(v_header);
            f_process.write(": ");
            f_process.write(v_request.rawHeader(v_header));
            f_process.write("\r\n");
        }
        qDebug() << "[T_HttpAccessBackend_Process::self_process_started(3)]";
        f_process.closeWriteChannel();
        qDebug() << "[T_HttpAccessBackend_Process::self_process_started(4)]";
    }
    void self_process_finished( int exitCode, QProcess::ExitStatus exitStatus )
    {
        qDebug() << "[T_HttpAccessBackend_Process::self_process_finished()]" << exitCode << exitStatus;
        enqueue_finished();
    }
    void self_process_readyReadStandardOutput()
    {
        qDebug() << "[T_HttpAccessBackend_Process::self_process_readyReadStandardOutput()]";
        if(!f_http_attr.parse_completed())
        {
            while(!f_http_attr.parse_completed() && f_process.canReadLine())
            {
                QByteArray v_line = f_process.readLine();
                v_line = v_line.trimmed();
                f_http_attr.parse_next_line(v_line);
            }
            if (!f_http_attr.parse_completed()) return;
            qDebug() << "[f_http_attr.toString()]" << f_http_attr.toString();
            enqueue_metaDataChanged();
        }
        if(f_process.bytesAvailable()>0)
        {
            enqueue_readyRead();
        }
    }
    void self_process_readyReadStandardError()
    {
        qDebug() << "[T_HttpAccessBackend_Process::self_process_readyReadStandardError()]";
        QByteArray v_bytes = f_process.readAllStandardError();
        if(v_bytes.endsWith('\n')) v_bytes.chop(1);
        v_bytes.replace('\r', "");
        QList<QByteArray> v_lines = v_bytes.split('\n');
        foreach(QByteArray v_line, v_lines)
        {
            v_line.prepend("<stderr> ");
            qDebug(v_line.constData());
        }
    }
};

#endif // T_BEND_PROCESS_H
